package cmd_utils

import (
	"errors"
	"fmt"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
	"github.com/spf13/viper"
	"log/slog"
	"os"
	"path/filepath"
	"strings"
)

const FlagPort = "port"
const FlagAllowOrigin = "allow-origin"      // 允许跨域的域名
const FlagChrome = "chrome"                 // 指定chrome 程序路径
const PageAddr = "page"                     // 默认打开的页面
const FlagConfigFile = "config-file"        // 程序配置文件位置
const UserDataDir = "user-data-dir"         // 浏览器 user-data-dir
const FlagChromeArgs = "chrome-args"        // 日志输出目录
const DontStartServer = "dont-start-server" // 不启用后台服务
const DBFile = "db"                         // 数据存储位置
const RuntimeJs = "runtime-js"              // 前台运行时js

const AppPrefix = "app."

var argsLogger = slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug}))

func GetStringArg(name string) string {
	return viper.GetString(name)
}
func GetStringSlices(name string) []string {
	return viper.GetStringSlice(name)
}

func GetIntArg(name string) int {
	return viper.GetInt(name)
}
func GetUIntArg(name string) uint {
	return viper.GetUint(name)
}

func GetServerPort() uint {
	return GetUIntArg(AppPrefix + FlagPort)
}

func GetChromePath() string {
	return GetStringArg(AppPrefix + FlagChrome)
}

// GetPageUrl 浏览器加载页面的地址
func GetPageUrl() string {
	return GetStringArg(AppPrefix + PageAddr)
}

func GetUserDataDir() string {
	return GetStringArg(AppPrefix + UserDataDir)
}

func GetDontStartServer() bool {
	flag := GetStringArg(AppPrefix + DontStartServer)
	return strings.Compare(flag, "yes") == 0
}

func GetDbFile() string {
	return GetStringArg(AppPrefix + DBFile)
}
func GetAllowOrigin() string {
	return GetStringArg(AppPrefix + FlagAllowOrigin)
}
func GetRuntimeBaseJs() string {
	s := GetStringArg(AppPrefix + RuntimeJs)
	if len(s) == 0 {
		s = "/runtime/base.js"
	}
	return s
}

func GetChromeArgs() []string {
	return viper.GetStringSlice(AppPrefix + FlagChromeArgs)
}

func ConfigViper(configFile string, prefix string, appCmd *cobra.Command) {
	appCmd.Flags().VisitAll(func(flag *pflag.Flag) {
		e := viper.BindPFlag(fmt.Sprintf("%s.%s", prefix, flag.Name), flag)
		if e != nil {
			panic(errors.New(fmt.Sprintf("bind flag %s failed", flag.Name)))
		}
	})
	if len(configFile) == 0 {
		defaultConfigFileName := "app"
		viper.SetConfigName(defaultConfigFileName)
		viper.SetConfigType("yaml")
		paths := []string{".", "$HOME/.dev-tools"}

		for _, pt := range paths {
			viper.AddConfigPath(pt)
		}

		e := viper.ReadInConfig()
		if e != nil {
			argsLogger.Warn("load config file error, use default parameters .", "err", e)
		}
	} else {
		viper.SetConfigFile(configFile)
		e := viper.ReadInConfig()
		if e != nil {
			argsLogger.Error("fatal error config file", "err", e)
		}
	}
}

var programPath string
var programDir string

func GetProgramPath() string {
	return programPath
}

func GetProgramDir() string {
	return programDir
}

func init() {
	programPath = os.Args[0]
	programDir = filepath.Dir(programPath)
}
